package com.zjhn.ds.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zjhn.ds.common.BizResult;
import com.zjhn.ds.common.exception.BizException;
import com.zjhn.ds.domain.dto.app.AppStationMonitorDto;
import com.zjhn.ds.domain.dto.app.CurrentTaskDto;
import com.zjhn.ds.domain.dto.app.QueueTaskDto;
import com.zjhn.ds.domain.entity.erp.*;
import com.zjhn.ds.domain.entity.jlw.*;
import com.zjhn.ds.mapper.*;
import com.zjhn.ds.param.AppStationMonitorParam;
import com.zjhn.ds.param.FinishTaskParam;
import com.zjhn.ds.param.ReportParam;
import com.zjhn.ds.param.SwipeCardParam;
import com.zjhn.ds.service.AppStationMonitorService;
import com.zjhn.ds.utils.CommonUtil;
import com.zjhn.ds.utils.base.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @BelongsProject: ds_jlw
 * @BelongsPackage: com.zjhn.ds.service.impl
 * @Author: sxt
 * @CreateTime: 2023-10-09  09:44
 * @Description:
 * @Version: 1.0
 */
@Slf4j
@Service
public class AppStationMonitorServiceImpl implements AppStationMonitorService {

    @Resource
    private CommonUtil commonUtil;

    @Resource
    private PlatformTransactionManager platformTransactionManager;

    @Resource
    private TransactionDefinition transactionDefinition;

    @Resource
    private AssignTaskMapper assignTaskMapper;

    @Resource
    private SwipeCardInfoMapper swipeCardInfoMapper;

    @Resource
    private ProTaskDetailMapper proTaskDetailMapper;

    @Resource
    private GroupStationMapper groupStationMapper;

    @Resource
    private GroupSpinnerMapper groupSpinnerMapper;

    @Resource
    private StationMapper stationMapper;

    @Resource
    private ProTaskMapper proTaskMapper;

    @Resource
    private TradeOrderDetailMapper tradeOrderDetailMapper;

    @Resource
    private ProBoxMapper proBoxMapper;

    @Resource
    private ReportRecordMapper reportRecordMapper;

    @Resource
    private OperatorMapper operatorMapper;


    /**
     * app机台监控页面数据
     *
     * @param param
     * @return
     */
    @Override
    public BizResult<List<AppStationMonitorDto>> stationMonitor(AppStationMonitorParam param) {
        List<AppStationMonitorDto> res = new ArrayList<>();

        // 挡车工负责工位信息
        List<GroupSpinner> groupSpinners = groupSpinnerMapper.selectList(new QueryWrapper<GroupSpinner>().eq("spinner_id", param.getSpinnerId()));
        if (groupSpinners.size() == 0)
            return BizResult.success(res);
        Set<String> groupIds = groupSpinners.stream().map(GroupSpinner::getGroupId).collect(Collectors.toSet());
        List<GroupStation> groupStations = groupStationMapper.selectList(new QueryWrapper<GroupStation>().in("group_id", groupIds));
        if (groupStations.size() == 0)
            return BizResult.success(res);
        Set<String> stationIds = groupStations.stream().map(GroupStation::getStationId).collect(Collectors.toSet());
        List<Station> stations = stationMapper.selectBatchIds(stationIds);

        // 获取机台当前刷卡信息
        List<SwipeCardInfo> swipeCardInfos = swipeCardInfoMapper.selectList(new QueryWrapper<SwipeCardInfo>().in("station_id", stationIds));
        Map<String, SwipeCardInfo> swipeCardInfoMap = new HashMap<>();
        List<String> assignTaskIds = new ArrayList<>();
        if (swipeCardInfos.size() > 0) {
            swipeCardInfoMap = swipeCardInfos.stream().collect(Collectors.toMap(SwipeCardInfo::getStationId, c -> c));
            assignTaskIds.addAll(swipeCardInfos.stream().map(SwipeCardInfo::getAssignTaskId).collect(Collectors.toList()));
        }

        // 获取刷卡对应的派工任务
        Map<String, AssignTask> assignTaskMap = new HashMap<>();
        if (assignTaskIds.size() > 0) {
            List<AssignTask> assignTasks = assignTaskMapper.selectBatchIds(assignTaskIds);
            assignTaskMap = assignTasks.stream().collect(Collectors.toMap(AssignTask::getTaskDetailId, c -> c));
        }

        for (Station station : stations) {
            AppStationMonitorDto build = AppStationMonitorDto.builder()
                    .stationId(station.getId())
                    .stationCode(station.getStationCode())
                    .stationName(station.getStationName())
                    .status(commonUtil.getStationStatus(station.getId()))
//                    .styleCode()
//                    .completeQty()
//                    .assignQty()
                    .build();

            SwipeCardInfo swipeCardInfo = swipeCardInfoMap.get(station.getId());
            if (swipeCardInfo != null)
                build.setStyleCode(swipeCardInfo.getStyleCode());

            AssignTask assignTask = assignTaskMap.get(station.getId());
            if (assignTask != null) {
                build.setAssignQty(assignTask.getAssignQty());
                build.setCompleteQty(assignTask.getCompleteQty());
            }

            res.add(build);
        }

        // 排序
        res = res.stream()
                .sorted(Comparator.comparing(c -> Integer.parseInt(c.getStationCode().replace("-", ""))))
                .collect(Collectors.toList());
        if (param.getOrder() == 2)
            res = res.stream().sorted(Comparator.comparing(AppStationMonitorDto::getStationCode).reversed()).collect(Collectors.toList());

        return BizResult.success(res);
    }

    /**
     * app获取工位当前刷卡任务
     *
     * @param stationId
     * @return
     */
    @Override
    public BizResult<CurrentTaskDto> currentTask(String stationId) {
        CurrentTaskDto res = CurrentTaskDto.builder().build();

        SwipeCardInfo swipeCardInfo = swipeCardInfoMapper.selectOne(new QueryWrapper<SwipeCardInfo>().eq("station_id", stationId));
        if (swipeCardInfo == null)
            return BizResult.success(res);

        // 获取对应明细
        ProTaskDetail proTaskDetail = proTaskDetailMapper.selectById(swipeCardInfo.getProTaskDetailId());
        if (proTaskDetail == null)
            return BizResult.fail("生产单明细不存在");

        // 明细派工任务
        List<AssignTask> assignTasks = assignTaskMapper.selectList(
                new QueryWrapper<AssignTask>()
                        .eq("task_detail_id", swipeCardInfo.getProTaskDetailId())
        );
        AssignTask assignTask = assignTaskMapper.selectById(swipeCardInfo.getAssignTaskId());

        res.setSwipeCardId(swipeCardInfo.getId());
        res.setAssignTaskId(assignTask.getId());
        res.setStyleCode(swipeCardInfo.getStyleCode());
        res.setColorMain(swipeCardInfo.getColorMain());
        res.setSize(swipeCardInfo.getSize());
        res.setNeedle(swipeCardInfo.getNeedle());
        res.setStationCompleteQty(assignTask.getCompleteQty());
        res.setStationAssignQty(assignTask.getAssignQty());
        res.setDetailCompleteQty(assignTasks.stream().map(AssignTask::getCompleteQty).reduce(BigDecimal::add).orElse(BigDecimal.ZERO));
        res.setDetailQty(BigDecimal.valueOf(proTaskDetail.getNumber()));
        res.setProBoxCode(swipeCardInfo.getProBoxCode());
        res.setProBoxBookJobQty(swipeCardInfo.getProBoxBookJobQty());
        res.setPlanQty(swipeCardInfo.getPlanQty());
        return BizResult.success(res);
    }

    /**
     * app获取工位排队任务
     *
     * @param stationId
     * @return
     */
    @Override
    public BizResult<List<QueueTaskDto>> queueTask(String stationId) {
        List<QueueTaskDto> res = new ArrayList<>();
        List<AssignTask> assignTasks = assignTaskMapper.selectList(
                new QueryWrapper<AssignTask>()
                        .eq("station_id", stationId)
                        .eq("task_status", 1)
                        .orderByAsc("begin_time")
        );
        if (assignTasks.size() > 0) {
            // 生产单
            Set<String> taskIds = assignTasks.stream().map(AssignTask::getTaskId).collect(Collectors.toSet());
            List<ProTask> proTasks = proTaskMapper.selectBatchIds(taskIds);
            Map<String, ProTask> proTaskMap = proTasks.stream().collect(Collectors.toMap(ProTask::getId, c -> c));

            Set<String> taskDetailIds = assignTasks.stream().map(AssignTask::getTaskDetailId).collect(Collectors.toSet());
            // 生产明细
            List<ProTaskDetail> proTaskDetails = proTaskDetailMapper.selectBatchIds(taskDetailIds);
            Map<String, ProTaskDetail> proTaskDetailMap = proTaskDetails.stream().collect(Collectors.toMap(ProTaskDetail::getId, c -> c));

            // 交易单明细
            Set<String> orderDetailIds = proTaskDetails.stream().map(ProTaskDetail::getTradeOrderDetailId).collect(Collectors.toSet());
            List<TradeOrderDetail> tradeOrderDetails = tradeOrderDetailMapper.selectBatchIds(orderDetailIds);
            Map<String, TradeOrderDetail> orderDetailMap = tradeOrderDetails.stream().collect(Collectors.toMap(TradeOrderDetail::getId, c -> c));

            // 当前刷卡信息
            SwipeCardInfo swipeCardInfo = swipeCardInfoMapper.selectOne(new QueryWrapper<SwipeCardInfo>().eq("station_id", stationId));
            for (AssignTask assignTask : assignTasks) {
                ProTask proTask = proTaskMap.get(assignTask.getTaskId());
                if (proTask == null)
                    continue;
                ProTaskDetail proTaskDetail = proTaskDetailMap.get(assignTask.getTaskDetailId());
                if (proTaskDetail == null)
                    continue;
                TradeOrderDetail tradeOrderDetail = orderDetailMap.get(proTaskDetail.getTradeOrderDetailId());
                if (tradeOrderDetail == null)
                    continue;

                // 预计完成天数
                Date finishDate = DateUtil.dateAddMinute(assignTask.getBeginTime(), assignTask.getRequire());
                Integer intervalDays = 0;
                if (finishDate.compareTo(new Date()) > 0)
                    intervalDays = DateUtil.intervalDays(new Date(), finishDate);

                QueueTaskDto build = QueueTaskDto.builder()
                        .assignTaskId(assignTask.getId())
                        .proTaskCode(proTask.getCode())
                        .assignQty(assignTask.getAssignQty())
                        .completeQty(assignTask.getCompleteQty())
                        .styleCode(tradeOrderDetail.getStyleCode())
                        .colorName(tradeOrderDetail.getColorName())
                        .needleCode(tradeOrderDetail.getNeedle())
                        .colorMain(tradeOrderDetail.getColorMain())
                        .size(tradeOrderDetail.getSize())
                        .finishDay(intervalDays)
                        .current(0)
                        .build();
                if (swipeCardInfo != null && build.getAssignTaskId().equals(swipeCardInfo.getId())) {
                    build.setSwipeCardId(swipeCardInfo.getId());
                    build.setCurrent(1);
                }
                res.add(build);
            }

        }

        return BizResult.success(res);
    }

    /**
     * app确认报工
     *
     * @param param
     * @return
     */
    @Transactional
    @Override
    public BizResult<?> report(ReportParam param) {
        // 报工人信息
        Operator operator = operatorMapper.selectOne(
                new QueryWrapper<Operator>()
                        .eq("UserNo", param.getBookJobUser())
                        .eq("IsDeleted", 0)
        );
        if (operator == null)
            return BizResult.fail("报工人不存在");

        SwipeCardInfo swipeCardInfo = swipeCardInfoMapper.selectById(param.getSwipeCardId());
        if (swipeCardInfo == null)
            return BizResult.fail("刷卡信息不存在");

        AssignTask assignTask = assignTaskMapper.selectById(swipeCardInfo.getAssignTaskId());
        if (assignTask == null)
            return BizResult.fail("派工信息不存在");

        // 卡信息
        MesProBox mesProBox = proBoxMapper.selectOne(
                new QueryWrapper<MesProBox>()
                        .eq("Code", swipeCardInfo.getProBoxCode())
                        .eq("IsDeleted", 0)
        );
        if (mesProBox == null) {
            log.error("====[ERROR]====AppStationMonitorServiceImpl====report 卡信息不存在 proBoxCode:{}", swipeCardInfo.getProBoxCode());
            throw new BizException("卡信息不存在");
        }

        // TODO 请求ERP接口报工

        // 派工完成数记录
        assignTask.setCompleteQty(assignTask.getCompleteQty().add(param.getBookJobQty()));
        assignTaskMapper.updateById(assignTask);
        // 报工记录
        ReportRecord reportRecord = ReportRecord.builder()
                .assignTaskId(assignTask.getId())
                .stationId(assignTask.getStationId())
                .proTaskDetailId(assignTask.getTaskDetailId())
//                .bookJobId()
                .proBoxCode(mesProBox.getCode())
                .styleCode(swipeCardInfo.getStyleCode())
                .colorMain(swipeCardInfo.getColorMain())
                .size(swipeCardInfo.getSize())
                .needle(swipeCardInfo.getNeedle())
                .realName(operator.getRealName())
                .userNo(operator.getUserNo())
                .bookJobQty(param.getBookJobQty())
                .build();
        reportRecordMapper.insert(reportRecord);
        return BizResult.success();
    }

    /**
     * app刷卡
     *
     * @param param
     * @return
     */
    @Override
    public synchronized BizResult<?> swipeCard(SwipeCardParam param) {
        // 开启事务
        TransactionStatus transactionStatus = platformTransactionManager.getTransaction(transactionDefinition);
        try {
            // 业务代码
            MesProBox mesProBox = proBoxMapper.selectOne(new QueryWrapper<MesProBox>()
                    .eq("Code", param.getCode())
                    .eq("IsDeleted", 0));
            if (mesProBox == null)
                return BizResult.fail("卡信息不存在");

            ProTaskDetail proTaskDetail = proTaskDetailMapper.selectById(mesProBox.getPDetailId());
            if (proTaskDetail == null)
                return BizResult.fail("生产明细不存在");
            TradeOrderDetail tradeOrderDetail = tradeOrderDetailMapper.selectById(proTaskDetail.getTradeOrderDetailId());
            if (tradeOrderDetail == null)
                return BizResult.fail("交易单明细不存在");

            // 派工任务
            AssignTask assignTask = assignTaskMapper.selectOne(
                    new QueryWrapper<AssignTask>()
                            .eq("task_detail_id", proTaskDetail.getId())
                            .eq("station_id", param.getStationId()));
            if (assignTask == null)
                return BizResult.fail("卡对应的派工任务不存在");

            SwipeCardInfo swipeCardInfo = swipeCardInfoMapper.selectOne(
                    new QueryWrapper<SwipeCardInfo>()
                            .eq("pro_task_detail_id", proTaskDetail.getId())
                            .eq("station_id", param.getStationId())
            );
            if (swipeCardInfo == null) {
                // 不存在刷卡信息
                swipeCardInfo = SwipeCardInfo.builder()
                        .assignTaskId(assignTask.getId())
                        .proTaskDetailId(proTaskDetail.getId())
                        .stationId(param.getStationId())
                        .styleCode(tradeOrderDetail.getStyleCode())
                        .colorMain(tradeOrderDetail.getColorMain())
                        .size(tradeOrderDetail.getSize())
                        .needle(tradeOrderDetail.getNeedle())
                        .pic(tradeOrderDetail.getImageUrl())
                        .proBoxCode(mesProBox.getCode())
                        .planQty(mesProBox.getPlanQty())
                        .proBoxBookJobQty(BigDecimal.valueOf(Integer.parseInt(mesProBox.getCurrentQty())))
                        .build();

                swipeCardInfoMapper.insert(swipeCardInfo);
            } else {
                // 存在刷卡信息
                swipeCardInfo.setAssignTaskId(assignTask.getTaskId());
                swipeCardInfo.setProTaskDetailId(proTaskDetail.getId());
                swipeCardInfo.setStationId(param.getStationId());
                swipeCardInfo.setStyleCode(tradeOrderDetail.getStyleCode());
                swipeCardInfo.setColorMain(tradeOrderDetail.getColorMain());
                swipeCardInfo.setSize(tradeOrderDetail.getSize());
                swipeCardInfo.setNeedle(tradeOrderDetail.getNeedle());
                swipeCardInfo.setPic(tradeOrderDetail.getImageUrl());
                swipeCardInfo.setProBoxCode(mesProBox.getCode());
                swipeCardInfo.setPlanQty(mesProBox.getPlanQty());
                swipeCardInfo.setProBoxBookJobQty(BigDecimal.valueOf(Integer.parseInt(mesProBox.getCurrentQty())));
                swipeCardInfoMapper.updateById(swipeCardInfo);
            }

            // 事务提交
            platformTransactionManager.commit(transactionStatus);
            return BizResult.success();
        } catch (Exception e) {
            log.error("====[ERROR]====AppStationMonitorServiceImpl====swipeCard 刷卡异常:{}", e.getMessage());
            // 事务回滚
            platformTransactionManager.rollback(transactionStatus);
            return BizResult.fail("刷卡异常");
        }
    }

    /**
     * app 派工任务完成
     * @param param
     * @return
     */
    @Transactional
    @Override
    public BizResult<?> finishTask(FinishTaskParam param) {
        if (StringUtils.isNotBlank(param.getSwipeCardId()))
            // 当前任务
            swipeCardInfoMapper.deleteById(param.getSwipeCardId());

        AssignTask assignTask = assignTaskMapper.selectById(param.getAssignTaskId());
        if (assignTask == null)
            return BizResult.fail("派工任务不存在");
        assignTask.setTaskStatus(2);
        assignTask.setCreateTime(new Date());
        assignTaskMapper.updateById(assignTask);
        return BizResult.success();
    }
}
